//
//
//  Created by xm on 2025/6/23.
//

#import "AncsConsumerBleClient.h"
#import <CoreBluetooth/CoreBluetooth.h>

@interface  AncsConsumerBleClient()<CBCentralManagerDelegate, CBPeripheralDelegate>

@property (strong, nonatomic) CBCentralManager *centralManager;
@property (strong, nonatomic) CBPeripheral *peripheral;


/** 外设写特征 */
@property (strong, nonatomic) CBCharacteristic *notificationCharacteristic;
@property (strong, nonatomic) CBCharacteristic *readCharacteristic;
@property (strong, nonatomic) CBCharacteristic *writeCharacteristic;

@property (nonatomic, strong) XMLogger *logger;
@property (nonatomic, strong) RACDisposable* disposable_status;
@property (nonatomic, strong) RACDisposable* disposable_charMerge;
@property (nonatomic, strong) NSTimer* checkTimer;
@property (nonatomic, assign) NSTimeInterval checkTimestamp;

@property(nonatomic, strong) dispatch_queue_t bleDataSendQueue;


@end

@implementation  AncsConsumerBleClient

static NSString* Service_ID = NORMAL_Service_ID;
static NSString* Notify_Char_ID = NORMAL_Notify_Char_ID;
static NSString* Read_Char_ID = NORMAL_Read_Char_ID;
static NSString* Write_Char_ID = NORMAL_Write_Char_ID;


#pragma mark - getter
- (XMLogger *)logger
{
    if(!_logger){
        _logger = [XMLogger loggerWithScopeName:NSStringFromClass(self.class)];
    }
    
    return _logger;
}

#pragma mark - api

- (dispatch_queue_t)bleDataSendQueue
{
    if(_bleDataSendQueue == nil){
        _bleDataSendQueue = dispatch_queue_create("AncsConsumerBleClient", DISPATCH_QUEUE_SERIAL);
    }
    
    return _bleDataSendQueue;
}


-(void) start
{
    self.logger.log(@"start");

    self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];

    [self watch];
    
}

-(void) sendData:(NSData*) data
{
    self.logger.log(@"sendData length:%ld", data.length);
    
    @weakify(self);
    dispatch_async(self.bleDataSendQueue, ^{
        @strongify(self);
//        NSTimeInterval t1 = [[NSDate date] timeIntervalSince1970] * 1000;
        
        [self.peripheral writeValue:data forCharacteristic:self.writeCharacteristic type:CBCharacteristicWriteWithResponse];
        
//        NSTimeInterval t2 = [[NSDate date] timeIntervalSince1970] * 1000;
//        self.logger.log(@"sendData use time:%f", t2 - t1);
    });
}
-(void) stop
{
    self.logger.log(@"stop");
    
    if(self.centralManager.isScanning){
        [self.centralManager stopScan];
        self.centralManager = nil;
    }
    if(self.disposable_charMerge){
        [self.disposable_charMerge dispose];
    }
    if(self.disposable_status){
        [self.disposable_status dispose];
    }
    
}

#pragma mark - methods


-(void)watch
{
  
}

-(void)startScanning{
    self.logger.log(@"startScanning");
    
    NSDictionary *option = @{
        CBCentralManagerScanOptionAllowDuplicatesKey : @NO,
        CBCentralManagerOptionShowPowerAlertKey: @YES
    };
    [self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:Service_ID]] options:option];
//
    
    BOOL isExtend =  [CBCentralManager supportsFeatures:CBCentralManagerFeatureExtendedScanAndConnect];
    self.logger.log(@"startScanning isExtend :%d", isExtend);
    
}


#pragma mark - CBCentralManagerDelegate

// 中心管理器状态更新回调
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    NSString* err = @"";
    switch (central.state) {
        case CBManagerStatePoweredOff:
            
            err = @"蓝牙未连接";
            [self handleConnectionError:err];
            break;
            
        case CBManagerStateUnauthorized:
            err = @"蓝牙未授权";
            [self handleConnectionError:err];
            break;
            
        case CBManagerStatePoweredOn:
            self.logger.log(@"蓝牙已开启");
            // 扫描特定服务的外设，这里使用一个示例UUID
            [self startScanning];
            break;
            
        default:
            self.logger.log(@"蓝牙状态异常: %ld", (long)central.state);
            err = @"蓝牙状态异常";
            [self handleConnectionError:err];
            break;
    }
}


// 发现外设回调
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI {
    NSString * localName = advertisementData[@"kCBAdvDataLocalName"];

    NSData *manufacturerData = advertisementData[CBAdvertisementDataManufacturerDataKey];

    self.logger.log(@"发现外设: %@ localName:%@ identifier:%@", peripheral.name, localName, peripheral.identifier.UUIDString);
    self.logger.log(@"发现外设: manufacturerData:%@", [AppHelper hexStringFromData:manufacturerData]);
    
    
    self.peripheral = peripheral;
    if(localName != nil){
        self.deviceName = localName;
    }else{
        self.deviceName = peripheral.name;
    }
    
    self.peripheral.delegate = self;
    
    NSDictionary *options = @{
        CBConnectPeripheralOptionNotifyOnConnectionKey: @NO,
         CBConnectPeripheralOptionNotifyOnDisconnectionKey: @NO,


                              
    };
    
    // 连接外设
    [central connectPeripheral:peripheral options:options];
}

// 连接外设成功回调
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    self.logger.log(@"连接外设成功");
    // 发现外设服务
    [peripheral discoverServices:@[[CBUUID UUIDWithString:Service_ID]]];
    [self.centralManager stopScan];
    
//    self.logger.log(@" MTU WithResponse:%ld",  [peripheral maximumWriteValueLengthForType:CBCharacteristicWriteWithResponse]);
//    self.logger.log(@" MTU WriteWithoutResponse:%ld",  [peripheral maximumWriteValueLengthForType:CBCharacteristicWriteWithoutResponse]);

}

// 连接外设失败回调
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    self.logger.log(@"连接外设失败: %@", error.localizedDescription);
    [self handleConnectionError:error.localizedDescription];
}
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error
{
    self.logger.log(@"连接断开: %@", error);
 
}

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral timestamp:(CFAbsoluteTime)timestamp isReconnecting:(BOOL)isReconnecting error:(nullable NSError *)error
{
    self.logger.log(@"连接断开 isReconnecting:%d error:%@" ,isReconnecting, error);
    
}


#pragma mark - CBPeripheralDelegate

// 发现服务回调
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    if (error) {
        NSString* err = [NSString stringWithFormat:@"发现服务失败: %@", error.localizedDescription];
        return;
    }
    
    // 遍历发现的服务
    for (CBService *service in peripheral.services) {
        self.logger.log(@"发现服务: %@", service.UUID);
        self.logger.log(@"ServiceUUID: %@", Service_ID);

        
        if(peripheral.canSendWriteWithoutResponse){
            self.logger.log(@"发现服务 外设可接受无响应数据");
        }
        self.logger.log(@"发现服务 开始搜索特性");
        // 发现服务中的特征
        NSArray* characters = @[
            [CBUUID UUIDWithString:Notify_Char_ID],
            [CBUUID UUIDWithString:Read_Char_ID],
            [CBUUID UUIDWithString:Write_Char_ID],
        ];
        [peripheral discoverCharacteristics:characters forService:service];
    }
}

// 发现特征回调
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    if (error) {
        NSString* err = [NSString stringWithFormat:@"发现特征失败: %@", error.localizedDescription];
        return;
    }
    
    // 遍历发现的特征
    for (CBCharacteristic *characteristic in service.characteristics) {
        
        self.logger.log(@"发现特征 %@", characteristic.UUID);

        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:Notify_Char_ID]]) {
            self.logger.log(@"发现通知特征 %@ properties:%ld", characteristic.UUID, characteristic.properties);
            self.notificationCharacteristic = characteristic;
            // 读取特征值
//            [peripheral readValueForCharacteristic:characteristic];
            // 订阅特征值变化
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        }
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:Read_Char_ID]]) {
            self.logger.log(@"发现可读特征 %@", characteristic.UUID);
            self.readCharacteristic = characteristic;
//            uint8_t cmd = 0x00;
//            NSData* data =[NSData dataWithBytes:&cmd length:1];
//            [self sendData:data];
       
        }
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:Write_Char_ID]]) {
            self.logger.log(@"发现可写特征 %@", characteristic.UUID);
            self.writeCharacteristic = characteristic;
//            uint8_t cmd = 0x00;
//            NSData* data =[NSData dataWithBytes:&cmd length:1];
//            [self sendData:data];
       
        }
        
        
    }
}

// 特征值更新回调
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        self.logger.log(@"更新特征值失败: UUID:%@ error:%@", characteristic.UUID.UUIDString, error.localizedDescription);
        return;
    }
    self.logger.log(@"更新特征值: %@ value:%@", characteristic.UUID.UUIDString, characteristic.value);
    // 处理特征值
    NSData *data = characteristic.value;
  
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic
             error:(NSError *)error {
    self.logger.log(@"订阅: %@", characteristic.UUID);
    if (error) {
        self.logger.log(@"订阅失败: %@", error.localizedDescription);
    } else {
        if (characteristic.isNotifying) {
            self.logger.log(@"订阅成功，特征 UUID: %@", characteristic.UUID);
        } else {
            self.logger.log(@"已取消订阅");
        }
    }
    

    
}


- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic
             error:(NSError *)error {
    
    
    if (error) {
        self.logger.log(@"写入失败: characteristic:%@ error:%@", characteristic.UUID.UUIDString,error.localizedDescription);

    } else {
//        self.logger.log(@"写入成功 characteristic:%@" ,characteristic.UUID.UUIDString);
        
    }
}

#pragma mark - others

-(void) handleConnectionError:(NSString*) message
{
    self.logger.log(@"handleConnectionError %@", message);

}

- (void)dealloc
{
    self.logger.log(@"dealloc");
}


@end
